package cn.itsource.ymcc.service.impl;

import cn.itsource.ymcc.domain.KillActivity;
import cn.itsource.ymcc.domain.KillCourse;
import cn.itsource.ymcc.dto.KillDto;
import cn.itsource.ymcc.dto.KillOrderDto;
import cn.itsource.ymcc.mapper.KillCourseMapper;
import cn.itsource.ymcc.service.IKillActivityService;
import cn.itsource.ymcc.service.IKillCourseService;
import cn.itsource.ymcc.util.AssertUtil;
import cn.itsource.ymcc.util.CodeGenerateUtils;
import com.baomidou.mybatisplus.mapper.EntityWrapper;
import com.baomidou.mybatisplus.service.impl.ServiceImpl;
import org.apache.rocketmq.client.producer.SendResult;
import org.apache.rocketmq.spring.core.RocketMQTemplate;
import org.redisson.api.RLock;
import org.redisson.api.RSemaphore;
import org.redisson.api.RedissonClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.messaging.support.MessageBuilder;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Set;

/**
 * <p>
 *  服务实现类
 * </p>
 *
 * @author Eric Chen
 * @since 2022-07-28
 */
@Service
public class KillCourseServiceImpl extends ServiceImpl<KillCourseMapper, KillCourse> implements IKillCourseService {
    @Autowired
    private IKillActivityService killActivityService;
    @Autowired
    private RedisTemplate<Object,Object> redisTemplate;
    @Autowired
    private RedissonClient redissonClient;
    @Autowired
    private RocketMQTemplate rocketMQTemplate;
    @Override
    public void add(KillCourse killCourse) {
        KillActivity killActivity = killActivityService.selectById(killCourse.getActivityId());
        AssertUtil.isNotNull(killActivity,"活动已经存在");
        killCourse.setCreateTime(new Date());
        killCourse.setStartTime(killActivity.getStartTime());
        killCourse.setEndTime(killActivity.getEndTime());
        killCourse.setTimeStr(killActivity.getTimeStr());
        killCourse.setPublishStatus(killActivity.getPublishStatus());
        killCourse.setKillLimit(1);
        killCourse.setKillSort(0);
        insert(killCourse);
    }

    @Override
    public List<KillCourse> selectByActiveId(Long id) {
        EntityWrapper<KillCourse> wrapper = new EntityWrapper<>();
        wrapper.eq("activity_id",id);
        List<KillCourse> killCourses = selectList(wrapper);

        return killCourses;
    }

    @Override
    public List<KillCourse> online() {
        List<KillCourse> list = new ArrayList<>();
        //拿到key的集合
        Set<Object> keys = redisTemplate.keys("active*");
        keys.forEach(key->{
            List values = redisTemplate.opsForHash().values(key.toString());
            list.addAll(values);

        });
        return list;
    }

    @Override
    public KillCourse onlineOne(Long id, Long activeId) {
        KillCourse o = (KillCourse)redisTemplate.opsForHash().get("active:"+activeId.toString(), id.toString());
        return o;
    }

    /**
     * 秒杀方法
     * @param dto
     * @return
     */
    @Override
    public String kill(KillDto dto) {
        Long loginId = 3l;


        KillCourse killCourse = onlineOne(dto.getKillCourseId(), dto.getActivityId());
        AssertUtil.isNotNull(killCourse,"非法");
        AssertUtil.isEquals(killCourse.getKillCode(),dto.getKillCode(),"秒杀码不一样");

        //减库存
        RSemaphore semaphore = redissonClient.getSemaphore("store" + killCourse.getId());
        //AssertUtil.isTrue(semaphore.tryAcquire(1),"没有库存");

        //预创单
        String orderNo = CodeGenerateUtils.generateOrderSn(loginId);
        KillOrderDto killOrderDto = new KillOrderDto(
                orderNo,loginId,killCourse.getCourseName(),killCourse.getKillPrice(),1,killCourse.getCourseId(),
                killCourse.getCoursePic(),killCourse.getId()
        );

//        //发送延迟消息处理下单超时
//        SendResult sendResult = rocketMQTemplate.syncSend(
//                "killtimeout-topic:killtimeout-tag",
//                MessageBuilder.withPayload(orderNo).build(),
//                2000,
//                6 // 10秒
//        );

        //订单存储redis
        String orderKey = "order:"+loginId+":"+orderNo;
        redisTemplate.opsForValue().set(orderKey,killOrderDto);
        return orderNo;
    }

    @Override
    public void killOrderOut(String s) {
        //添加分布式锁
        RLock lock = redissonClient.getLock("lock:" + s);
        lock.lock();
        try {
            KillOrderDto o = (KillOrderDto)redisTemplate.opsForValue().get(s);
            //下单成功不处理
            if (o == null)return;
            //退库存
            RSemaphore semaphore = redissonClient.getSemaphore("store" + o.getKillId());
            semaphore.release(o.getCount());

            //删除宇创单
            redisTemplate.delete(s);
        }finally {
            if (lock.isLocked())lock.unlock();

        }



    }


}
